package fiuba.algo3.XMLProcessor.EntradaSalida;

import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import fiuba.algo3.XMLProcessor.nucleo.Nodo;
import fiuba.algo3.XMLProcessor.nucleo.NodoAtributo;
import fiuba.algo3.XMLProcessor.nucleo.NodoDocumento;
import fiuba.algo3.XMLProcessor.nucleo.NodoTexto;
import fiuba.algo3.XMLProcessor.nucleo.NodoXML;

public class ImpresoraNodos
{
	FileWriter fileWriter;
	
	public ImpresoraNodos(String nombreArchivo)
	{
		try
		{
			fileWriter = new FileWriter(nombreArchivo, false);
		}
		catch (IOException ex)
		{
			Logger.getLogger(ImpresoraNodos.class.getName()).log(Level.SEVERE, "ImpresoraNodos: No se puede trabajar con el archivo <" + nombreArchivo + ">", ex);
			fileWriter = null;
		}
	}

	public void cerrar()
	{
		try
		{
			fileWriter.close();
		}
		catch (IOException ex)
		{
			Logger.getLogger(ImpresoraNodos.class.getName()).log(Level.SEVERE, "ImpresoraNodos: no se pudo cerrar el archivo", ex);
		}
	}

	private void imprimir(NodoTexto nodoTexto, int identacion)
	{
		if (fileWriter == null)
			return;

		try
		{
			identar(identacion);
//			fileWriter.write("<Texto>");
			fileWriter.write(nodoTexto.toString());
//			fileWriter.write("</Texto>");
			fileWriter.write('\n');
		}
		catch (IOException ex)
		{
			Logger.getLogger(ImpresoraNodos.class.getName()).log(Level.SEVERE, "ImpresoraNodos: No se puede volcar un nodo de Texto al archivo ", ex);
		}
	}

	private void imprimir(NodoAtributo nodoAtributo)
	{
		if (fileWriter == null)
			return;

		try
		{
			fileWriter.write(nodoAtributo.toString());
		}
		catch (IOException ex)
		{
			Logger.getLogger(ImpresoraNodos.class.getName()).log(Level.SEVERE, "ImpresoraNodos: No se puede volcar un nodo atributo al archivo ", ex);
		}
	}

	private void imprimir(List<NodoAtributo> listadoNodosAtributos)
	{
		if (fileWriter == null)
			return;

		try
		{
			for (NodoAtributo nodoAtributo : listadoNodosAtributos)
			{
				fileWriter.write(" ");
				fileWriter.write(nodoAtributo.toString());
			}
		}
		catch (IOException ex)
		{
			Logger.getLogger(ImpresoraNodos.class.getName()).log(Level.SEVERE, "ImpresoraNodos: No se puede volcar un nodo atributo al archivo ", ex);
		}
	}

	private void imprimirRetorno() throws IOException
	{
		fileWriter.write('\n');
	}
	
	private void imprimir(Nodo nodo, int identacion)
	{
		if (fileWriter == null)
			return;

		try
		{
			identar(identacion);
			fileWriter.write("<");
			fileWriter.write(nodo.nombre());
			List<NodoAtributo> listadoNodosAtributos = nodo.obtenerAtributos();
			if (!listadoNodosAtributos.isEmpty())
				ImpresoraNodos.this.imprimir(listadoNodosAtributos);
			List<NodoXML> listadoNodos = nodo.obtenerHijos();
			if (listadoNodos.isEmpty())
				fileWriter.write("/");
			else
			{
				fileWriter.write(">");
				imprimirRetorno();
				for (NodoXML nodoHijo : listadoNodos)
					imprimir(nodoHijo, identacion+1);
				identar(identacion);
				fileWriter.write("</" + nodo.nombre());
			}
			fileWriter.write(">");
			imprimirRetorno();
		}
		catch (IOException ex)
		{
			Logger.getLogger(ImpresoraNodos.class.getName()).log(Level.SEVERE, "ImpresoraNodos: No se puede volcar un nodo atributo al archivo ", ex);
		}
	}

	private void identar(int identacion)
	{
		for(int i = 0; i < identacion; i++)
		{
			try
			{
				fileWriter.write('\t');
			}
			catch (IOException ex)
			{
				Logger.getLogger(ImpresoraNodos.class.getName()).log(Level.SEVERE, "ImpresoraNodos: No se pueden volcar sangrias al archivo", ex);
			}
		}
	}

	private void imprimir(NodoXML nodoXML, int identacion)
	{
		if (fileWriter == null)
			return;

		String valor = nodoXML.getClass().getName();
		if (valor.equals("fiuba.algo3.XMLProcessor.nucleo.NodoTexto"))
			imprimir((NodoTexto)nodoXML, identacion);
		else if (valor.equals("fiuba.algo3.XMLProcessor.nucleo.Nodo"))
			imprimir((Nodo)nodoXML, identacion);
	}

	public void imprimir(NodoDocumento nodoDocumento)
	{
		if (fileWriter == null)
			return;

		try
			{
				fileWriter.write(nodoDocumento.cabecera());
				imprimirRetorno();
				imprimir(nodoDocumento.raiz(), 0);
			}
		catch (IOException ex)
		{
			Logger.getLogger(ImpresoraNodos.class.getName()).log(Level.SEVERE, "ImpresoraNodos: No se puede volcar un nodo documento al archivo ", ex);
		}
	}
}
